package com.cloudeasy.user.controller.admin;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cloudeasy.api.enums.ResultCodeEnum;
import com.cloudeasy.api.util.ResultUtil;
import com.cloudeasy.api.vo.PageResult;
import com.cloudeasy.api.vo.Result;
import com.cloudeasy.api.vo.user.RolePermissionVO;
import com.cloudeasy.core.bean.JwtParser;
import com.cloudeasy.user.po.Permission;
import com.cloudeasy.user.po.Role;
import com.cloudeasy.user.po.RolePermission;
import com.cloudeasy.user.service.PermissionService;
import com.cloudeasy.user.service.RolePermissionService;
import com.cloudeasy.user.service.RoleService;
import com.cloudeasy.user.service.expand.VerifyPermissionService;
import com.cloudeasy.user.util.IPageUtil;
import com.cloudeasy.user.util.RolePermissionUtil;
import com.cloudeasy.user.util.RoleUtil;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@CrossOrigin
@RequestMapping("/role_permission")
public class RolePermissionController {

    private final RoleService roleService;

    private final RolePermissionService rolePermissionService;

    private final PermissionService permissionService;

    private final VerifyPermissionService verifyPermissionService;

    private final JwtParser jwtParser;

    public RolePermissionController(RoleService roleService, RolePermissionService rolePermissionService, PermissionService permissionService, VerifyPermissionService verifyPermissionService, JwtParser jwtParser) {
        this.roleService = roleService;
        this.rolePermissionService = rolePermissionService;
        this.permissionService = permissionService;
        this.verifyPermissionService = verifyPermissionService;
        this.jwtParser = jwtParser;
    }

    /**
     * 获取单个角色的角色权限记录
     *
     * @param roleId 角色Id
     * @return {@link List<RolePermissionVO>}的{@link ResultUtil}
     */
    @GetMapping("/{roleId}")
    public Result<List<RolePermissionVO>> list(@PathVariable("roleId") String roleId) {
        Role role = roleService.getById(roleId);

        List<RolePermission> rolePermissions = rolePermissionService.listByRoleIds(Collections.singletonList(roleId));

        List<Permission> permissions = obtainPermissions(rolePermissions);

        return ResultUtil.success(RolePermissionUtil.convert(Collections.singletonList(role), rolePermissions, permissions));
    }

    /**
     * 获取角色权限记录
     *
     * @param roleIds 角色Id列表
     * @return {@link List<RolePermissionVO>}的{@link ResultUtil}
     */
    @GetMapping
    public Result<List<RolePermissionVO>> list(@RequestParam(value = "roleIds", required = false) List<String> roleIds) {
        QueryWrapper<Role> queryWrapper = RoleUtil.compose(roleIds, null, null);
        List<Role> roles = roleService.list(queryWrapper);

        if (roleIds == null || roleIds.size() == 0) {
            roleIds = roles.stream().map(Role::getId).collect(Collectors.toList());
        }

        List<RolePermission> rolePermissions = rolePermissionService.listByRoleIds(roleIds);

        List<Permission> permissions = obtainPermissions(rolePermissions);

        return ResultUtil.success(RolePermissionUtil.convert(roles, rolePermissions, permissions));
    }

    /**
     * 分页获取角色权限记录
     *
     * @param roleIds 角色Id列表
     * @param page    页数
     * @param size    每页大小
     * @return {@link PageResult<RolePermissionVO>}的{@link ResultUtil}
     */
    @GetMapping("/{page}/{size}")
    public Result<PageResult<RolePermissionVO>> list(@RequestParam(value = "roleIds", required = false) List<String> roleIds,
                                                     @PathVariable("page") Integer page,
                                                     @PathVariable("size") Integer size) {
        QueryWrapper<Role> queryWrapper = RoleUtil.compose(roleIds, null, null);
        IPage<Role> roleTempIPage = IPageUtil.compose(page, size);

        IPage<Role> roleIPage = roleService.page(roleTempIPage, queryWrapper);

        if (roleIds == null || roleIds.size() == 0) {
            roleIds = roleIPage.getRecords().stream().map(Role::getId).collect(Collectors.toList());
        }

        List<RolePermission> rolePermissions = rolePermissionService.listByRoleIds(roleIds);

        List<Permission> permissions = obtainPermissions(rolePermissions);

        return ResultUtil.success(RolePermissionUtil.convert(roleIPage, rolePermissions, permissions));
    }

    /**
     * 为角色赋予权限
     *
     * @param authentication {@link Authentication}
     * @param roleId         角色Id
     * @param permissionId   权限Id
     * @param authorize      可授权
     * @return {@link Result<Boolean>}
     */
    @PostMapping("/{roleId}/{permissionId}/{authorize}")
    public Result<Boolean> authorize(Authentication authentication,
                                     @PathVariable("roleId") String roleId,
                                     @PathVariable("permissionId") String permissionId,
                                     @PathVariable("authorize") Boolean authorize) {
        String operateUserId = (String) jwtParser.getOnBody(authentication, "userId");
        if (verifyPermissionService.canAuthorize(permissionId, operateUserId)) {
            return ResultUtil.success(rolePermissionService.save(roleId, permissionId, authorize));
        }
        return ResultUtil.failure(ResultCodeEnum.NO_PERMISSION_OPERATE);
    }

    /**
     * 更改授权
     *
     * @param authentication {@link Authentication}
     * @param roleId         角色Id
     * @param permissionId   权限Id
     * @param authorize      可授权
     * @return {@link Result<Boolean>}
     */
    @PutMapping("/{roleId}/{permissionId}/{authorize}")
    public Result<Boolean> changeAuthorize(Authentication authentication,
                                           @PathVariable("roleId") String roleId,
                                           @PathVariable("permissionId") String permissionId,
                                           @PathVariable("authorize") Boolean authorize) {
        String operateUserId = (String) jwtParser.getOnBody(authentication, "userId");
        if (verifyPermissionService.canAuthorize(permissionId, operateUserId)) {
            return ResultUtil.success(rolePermissionService.changeAuthorize(roleId, permissionId, authorize));
        }
        return ResultUtil.failure(ResultCodeEnum.NO_PERMISSION_OPERATE);
    }

    /**
     * 移除角色的权限
     *
     * @param authentication {@link Authentication}
     * @param roleId         角色Id
     * @param permissionId   权限Id
     * @return {@link Result<Boolean>}
     */
    @DeleteMapping("/{roleId}/{permissionId}")
    public Result<Boolean> changeAuthorize(Authentication authentication,
                                           @PathVariable("roleId") String roleId,
                                           @PathVariable("permissionId") String permissionId) {
        String operateUserId = (String) jwtParser.getOnBody(authentication, "userId");
        if (verifyPermissionService.canAuthorize(permissionId, operateUserId)) {
            return ResultUtil.success(rolePermissionService.removePermission(roleId, permissionId));
        }
        return ResultUtil.failure(ResultCodeEnum.NO_PERMISSION_OPERATE);
    }

    /**
     * 获取相关权限列表
     *
     * @param rolePermissions {@link List<RolePermission>}
     * @return {@link List<Permission>}
     */
    private List<Permission> obtainPermissions(List<RolePermission> rolePermissions) {
        List<String> permissionIds = rolePermissions.stream().map(RolePermission::getPermissionId).collect(Collectors.toList());

        List<Permission> permissions = new ArrayList<>();
        if (permissionIds.size() > 0) {
            permissions.addAll(permissionService.list(permissionIds));
        }

        return permissions;
    }
}
